package graphics.datastructures;

import static util.MatrixOperationsF.ar;
import static util.MatrixOperationsF.dist;
import static util.MatrixOperationsF.negate;
import graphics.raytracing.CastResult;
import graphics.raytracing.Ray;
import graphics.raytracing.Tracable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

import util.MatrixOperationsF;

public class SimpleMesh<T extends Tracable<? extends Tracable<T>>> implements Model<T> {
	/**
	 * 
	 */
	private static final long serialVersionUID = -6361804604570107725L;
	/**
	 * 
	 */
	private Collection<T> _content = Collections
			.synchronizedCollection(new ArrayList<T>());

	public void add(T t) {
		_content.add(t);
	}
	public CastResult<T> cast(Ray ray) {
		// determine closest
		
		float dist = Float.MAX_VALUE;
		CastResult<T> rv = null;
		for (T t : _content) {
			CastResult<T> temp = ((Tracable<T>) t).cast(ray);
			if (temp == null)
				continue;
			float d = dist(MatrixOperationsF.add(ray.getOrigin(),
					negate(temp.getLocation())));
			if (d < dist) {
				rv = temp;
				dist = d;
			}
		}

		return rv;
	}

	@Override
	public float[][] getBB() {
		float[][] rv = new float[2][];
		rv[0] = ar(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);
		rv[1] = negate(rv[0]);
		for (Tracable t : getTracables()) {
			float[][] _coords = t.getBB();
			for (int xyz = 0; xyz < 3; xyz++) {
				rv[0][xyz] = Math.min(rv[0][xyz], _coords[0][xyz]);
				rv[1][xyz] = Math.max(rv[1][xyz], _coords[1][xyz]);
			}

		}
		return rv;
	}


	@Override
	public Collection<T> getTracables() {
		return _content;
	}

	@Override
	public BoundingBox getBoundingBox() {
		return new BoundingBox(getBB());
	}

}
